﻿// developer Chris pembroke x00115839
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace bmiCountAllCategorySearchMiniProjMethod  // to develop the method to select BMI percentile  category for a single child 
{
    public class BmiCategoryFinder  // this class in the actual project will be the controller class
    {
        // these fields are needed in the actual project 
        private static string underWeight;  // a bmi percentile categories  will be worked out using the algorithm tables in the 2D arrays
        private static string healthyWeight; // a bmi percentile categories  will be worked out using the algorithm tables in the 2D arrays
        private static string overWeight;   // a bmi percentile categories  will be worked out using the algorithm tables in the 2D arrays
        private static string obeseWeight;  // a bmi percentile categories  will be worked out using the algorithm tables in the 2D arrays

        private static double[,] boysPercentileAlgorithm = new double[,]   // declare and initialize in memory the boys percentile category algorithm table
             {
                {5.0, 13.8, 16.8, 18.0},                       // a 2D array with 5 rows and 4 columns note 1st column is ordered
                {5.5, 13.8, 16.8, 18.2},                       // note first column is the age the other columns are bmi readings all doubles 
                {6.0, 13.7, 17.0, 18.4},
                {6.5, 13.7, 17.2, 18.6},
                {7.0, 13.7, 17.4, 19.0}
             };

        private static double[,] girlsPercentileAlgorithm = new double[,]   // declare and initialize in memory the girls percentile category algorithm table
            {
                {5.0, 13.5, 16.8, 18.2},                       // a 2D array with 5 rows and 4 columns note 1st column is ordered
                {5.5, 13.4, 16.9, 18.4},                       // note first column is the age the other columns are bmi readings all doubles 
                {6.0, 13.4, 17.0, 18.8},
                {6.5, 13.4, 17.2, 19.2},
                {7.0, 13.4, 17.6, 19.6}
            };

        // these fields are solely to develop apart from the project the method to select the percentile category
        private static double age;   // this in the actual project will be calculated using a method
        private static double bmi;   // this in the actual project will be calculated using a method
        private static string gender;  // this in the actual project will come via a query search on the class of  children table 

        public static string findChildsPercentileCategory(double age, double bmi, string gender) // method to determine which percentile category
        {
            gender = gender.ToLower();
            int boysAgeRowIndex;  // the index of the row in the algorithm array for that childs age who we are searching for
            int girlsAgeRowIndex;

            // 1st determine which algorithm array by checking which gender male or felmale
            if (gender == "m")  // if boy
            {

                boysAgeRowIndex = boysAgeBinarySearch(age);  // call method to search algoritm array for the age row
                string boysPercentileCategory = calcBoysPercentileCategory(boysAgeRowIndex, bmi); // call method to work out the category from the algorithm array 
                return boysPercentileCategory;
            }
            else  // if girl
            {
                girlsAgeRowIndex = girlsAgeBinarySearch(age); // call method to search algoritm array for the age row
                string girlsPercentileCategory = calcGirlsPercentileCategory(girlsAgeRowIndex, bmi); // call method to work out the category from the algorithm array 
                return girlsPercentileCategory;
            }
        } // close of method findChildspercentilecategory

        public static int boysAgeBinarySearch(double age)  // used on the algorithm arrays to find a match to age in the first column returns the row index 
        {
            // assume input values are validated on server and client sides before getting to call this method
            // can use a binary sort on the arrays first column as is ordered  is most efficient on ordered columns is order O(log n) efficiency
            int bottom = 0;
            int middle;
            int top = boysPercentileAlgorithm.GetUpperBound(0);   // gets the last index of the first column in the array ie number of rows
            int ageIndex = -1;  // declare and initialise the requirred  return index 
            while (bottom <= top)
            {
                middle = (bottom + top) / 2;  // note integer division truncates 

                if (boysPercentileAlgorithm[middle, 0] == age)
                {
                    ageIndex = middle;
                    return ageIndex;
                }
                else if (boysPercentileAlgorithm[middle, 0] > age)
                {
                    top = middle - 1;
                }
                else
                {
                    bottom = middle + 1;
                }
            }
            return ageIndex;

        } // close of method boysAgebinarysearch

        public static string calcBoysPercentileCategory(int rowIndex, double bmi) // method to calculate category from the algorithm array 
        {
            if (bmi < boysPercentileAlgorithm[rowIndex, 1])
            {
                return "Under Weight";
            }
            else if ((bmi >= boysPercentileAlgorithm[rowIndex, 1]) && (bmi < boysPercentileAlgorithm[rowIndex, 2]))
            {
                return "Healthy Weight";
            }
            else if ((bmi >= boysPercentileAlgorithm[rowIndex, 2]) && (bmi < boysPercentileAlgorithm[rowIndex, 3]))
            {
                return "Over Weight";
            }
            else                            // after previous checks only option left is obese ie. > algorithmArray[rowIndex,3]
            {
                return "Obese Weight";
            }
        } // close of method calcBoysPercentileCategory

        public static int girlsAgeBinarySearch(double age)  // used on the algorithm arrays to find a match to age in the first column returns the row index 
        {
            // assume input values are validated on server and client sides before getting to call this method
            // can use a binary sort on the arrays first column as is ordered  is most efficient on ordered columns is order O(log n) efficiency
            int bottom = 0;
            int middle;
            int top = girlsPercentileAlgorithm.GetUpperBound(0);   // gets the last index of the first column in the array ie number of rows
            int ageIndex = -1;  // declare and initialise the requirred  return index 
            while (bottom <= top)
            {
                middle = (bottom + top) / 2;  // note integer division truncates 

                if (girlsPercentileAlgorithm[middle, 0] == age)
                {
                    ageIndex = middle;
                    return ageIndex;
                }
                else if (girlsPercentileAlgorithm[middle, 0] > age)
                {
                    top = middle - 1;
                }
                else
                {
                    bottom = middle + 1;
                }
            }
            return ageIndex;

        } // close of method boysAgebinarysearch

        public static string calcGirlsPercentileCategory(int rowIndex, double bmi) // method to calculate category from the algorithm array 
        {
            if (bmi < girlsPercentileAlgorithm[rowIndex, 1])
            {
                return "Under Weight";
            }
            else if ((bmi >= girlsPercentileAlgorithm[rowIndex, 1]) && (bmi < girlsPercentileAlgorithm[rowIndex, 2]))
            {
                return "Healthy Weight";
            }
            else if ((bmi >= girlsPercentileAlgorithm[rowIndex, 2]) && (bmi < girlsPercentileAlgorithm[rowIndex, 3]))
            {
                return "Over Weight";
            }
            else                            // after previous checks only option left is obese ie. > algorithmArray[rowIndex,3]
            {
                return "Obese Weight";
            }
        } // close of method calcgirlsPercentileCategory

    } // close of class bmicategoryfinder

    public class ExecuteProgram
    {
        static void Main(string[] args)
        {
            Console.WriteLine("METHODS NEEDED TO FIND PERCENTILE CATEGORY FOR ONE CHILD NO COUNT");
            Console.WriteLine();
            try
            {
                bool anotherCalc = true;

                while (anotherCalc == true)
                {
                    string s;
                    Console.Write("Enter a test AGE one of 5, 5.5, 6, 6.5, 7:- ");
                    double age = double.Parse(Console.ReadLine());
                    if ((age != 5.0) && (age != 5.5) && (age != 6.0) && (age != 6.5) && (age != 7.0))
                    {
                        throw new IndexOutOfRangeException("Error - age out of range");
                    }

                    Console.Write("Enter a test BMI between 10 and 50 :- ");
                    double bmi = double.Parse(Console.ReadLine());
                    if ((bmi < 10) || (bmi > 50))
                    {
                        throw new IndexOutOfRangeException("Error - bmi out of range");
                    }

                    Console.Write("Enter Gender as either 'M' or 'F':- ");
                    string gender = Console.ReadLine().ToLower();
                    if ((gender != "m") && (gender != "f"))
                    {
                        throw new ArgumentException("Error - gender must be M or F");
                    }

                    if (gender == "m")
                    {
                        s = "Boy";
                    }
                    else
                    {
                        s = "Girl";
                    }


                    // string category = BmiCategoryFinder.FindPercentileCategory(age, bmi, gender); // working on its own own
                    //int ageindex = BmiCategoryFinder.boysBinarySearch(age); // working on its own now
                    // string category =  BmiCategoryFinder.calcBoysPercentileCategory(2,17.5); //  working on its own now
                    Console.WriteLine("The Percentile Category for a {0} of age {1} with a BMI of {2} is {3}.\n", s, age, bmi, BmiCategoryFinder.findChildsPercentileCategory(age, bmi, gender));
                    //Console.WriteLine("test return  {0}", BmiCategoryFinder.FindPercentileCategory(age, bmi, gender));

                    Console.WriteLine();
                    Console.Write("To run another category Search type 'y':- ");
                    string x = Console.ReadLine().ToLower();
                    if (x != "y")
                    {
                        anotherCalc = false;
                    }
                }
            } // close of try block
            catch (Exception e)
            {
                Console.WriteLine("Caught an Exception! {0}", e.Message);
            } // close of catch block

            Console.WriteLine();
            Console.Write("Press ENTER to Exit!");
            Console.ReadKey();


        } // close of main method

    } // close of class executeprogram

} // close of namespace

